﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
using System.Web.Security;
using System.Xml;
using Chire.ChireInter.Fanyi;
using Chire.ChireInter.Wechat;
using Newtonsoft.Json;

namespace Chire.wechat
{
    /// <summary>
    /// WechatAES 的摘要说明
    /// </summary>
    public class WechatAES : IHttpHandler
    {
        HttpContext contextWithBase;
        string signature = "";
        string timestamp = "";
        string nonce = "";
        string echostr = "";
        string postInfo = "";
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            contextWithBase = context;
            analysisInfo();
        }

        #region 验证信息
        public void analysisInfo()
        {
            signature = HttpContext.Current.Request.QueryString["signature"].ToString();
            timestamp = HttpContext.Current.Request.QueryString["timestamp"].ToString();
            nonce = HttpContext.Current.Request.QueryString["nonce"].ToString();
            echostr = HttpContext.Current.Request.QueryString["echoStr"];

            wechatInit();
            actionManager();
        }
        #endregion


        #region 插入数据
        public void insertIntoDiary(string info, string name,string openid)
        {
            // 连接数据库
            SqlConnection sqlcon = new SqlConnection(ConfigurationManager.ConnectionStrings["connection"].ConnectionString);
            sqlcon.Open();
            string StrInsert = "";
            StrInsert = "insert into wechatEvent(info,name,openid,datetime) values(@info,@name,@openid,@datetime)";
            SqlCommand cmd = new SqlCommand(StrInsert, sqlcon);
            // 添加参数并且设置参数值
            // 1. 作者id
            cmd.Parameters.Add("@info", SqlDbType.VarChar, 50000);
            cmd.Parameters["@info"].Value = info;

            cmd.Parameters.Add("@name", SqlDbType.VarChar, 50000);
            cmd.Parameters["@name"].Value = name;

            cmd.Parameters.Add("@openid", SqlDbType.VarChar, 50000);
            cmd.Parameters["@openid"].Value = openid;

            cmd.Parameters.Add("@datetime", SqlDbType.VarChar, 50000);
            cmd.Parameters["@datetime"].Value = DateTime.Now.ToString();
            
            // 执行插入数据的操作
            cmd.ExecuteNonQuery();
            sqlcon.Close();

        }
        #endregion

        #region 微信封装
      
        public void wechatInit() {
            Stream stream = System.Web.HttpContext.Current.Request.InputStream;
            Byte[] postBytes = new Byte[stream.Length];
            stream.Read(postBytes, 0, (Int32)stream.Length);
            string postXmlStr = Encoding.UTF8.GetString(postBytes);

            if (!string.IsNullOrEmpty(postXmlStr))
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(postXmlStr);

                XmlNode rootNode = doc.SelectSingleNode("xml");
                XmlNodeList xn1 = rootNode.ChildNodes;

                string ToUserName = xn1.Item(0).InnerText;
                string FromUserName = xn1.Item(1).InnerText;

                string MsgType = xn1.Item(3).InnerText;
                string Content = xn1.Item(4).InnerText;

                Dictionary<string, string> temp = new Dictionary<string, string>();
                string back = "";
                // 1. 判断是否为中文
                if (MsgType.Equals("event") == true) {
            
                    string eventStr = xn1.Item(4).InnerText;
                 
                    if (eventStr.Equals("LOCATION") == true)
                    {
                        Wechat_Action wechatAction = new Wechat_Action();
                        string lat = xn1.Item(5).InnerText;
                        string lon = xn1.Item(6).InnerText;
                        wechatAction.wechatLocationMainManager(FromUserName, lat, lon);
                    }
                }
                else if (MsgType.Equals("text") == true) {
                    if (Content.Equals("视频") == true)
                    {
                        temp.Add("ToUserName", FromUserName);
                        temp.Add("FromUserName", ToUserName);
                        temp.Add("CreateTime", ConvertDateTimeInt(DateTime.Now).ToString());
                        temp.Add("MsgType", "video");
                        temp.Add("MediaId", "Zt98jTR_lEMw08JUtMQbwDPGXMqNHjFS1FzNCeDXgpY");
                        temp.Add("Title", "日语");
                        temp.Add("Description", "哈哈哈");

                        string back1 = dicToXML(temp);
                        // 1. 进行插入
                        int index1 = back1.IndexOf("<MediaId>");
                        int index2 = back1.IndexOf("</xml>");
                        string back2 = back1.Insert(index1,"<Video>");
                        string back3 = back2.Insert(index2, "</Video>");
                        back = back3;
                    }
                    else if (Content.Equals("教材") == true) {
                        temp.Add("ToUserName", FromUserName);
                        temp.Add("FromUserName", ToUserName);
                        temp.Add("CreateTime", ConvertDateTimeInt(DateTime.Now).ToString());
                        temp.Add("MsgType", "image");
                        temp.Add("MediaId", "Zt98jTR_lEMw08JUtMQbwBJ--qNTogDCYYB_GW20pOw");
                    

                        string back1 = dicToXML(temp);
                        // 1. 进行插入
                        int index1 = back1.IndexOf("<MediaId>");
                        int index2 = back1.IndexOf("</xml>");
                        string back2 = back1.Insert(index1, "<Image>");
                        string back3 = back2.Insert(index2, "</Image>");
                        back = back3;

                        insertIntoDiary(back, postXmlStr, FromUserName);

                    }
                    else
                    {
                        temp.Add("ToUserName", FromUserName);
                        temp.Add("FromUserName", ToUserName);
                        temp.Add("CreateTime", ConvertDateTimeInt(DateTime.Now).ToString());
                        temp.Add("MsgType", "text");
                        Fanyi_Manager manager = new Fanyi_Manager();
                        string eninfo = manager.fanyi(Content);

                        temp.Add("Content", eninfo);
                        back = dicToXML(temp);

                        insertIntoDiary(Content, postXmlStr, FromUserName);
                    }
                }

                JsonSerializer serializer = new JsonSerializer();
                StringWriter sw = new StringWriter();
                serializer.Serialize(new JsonTextWriter(sw), back);
                string info = sw.GetStringBuilder().ToString();
                contextWithBase.Response.Write(sw.GetStringBuilder().ToString());
            }

        }
        #endregion

        #region 时间戳转换
        public long ConvertDateTimeInt(System.DateTime time)
        {
            DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc));
            TimeSpan ts = (time - startTime);

            return (long)ts.TotalSeconds;
        }
        #endregion


        #region dic to xml
        public string dicToXML(Dictionary<string, string> dics)
        {
            JsonSerializer serializer = new JsonSerializer();
            StringWriter sw = new StringWriter();
            serializer.Serialize(new JsonTextWriter(sw), dics);
            string info = sw.GetStringBuilder().ToString();
            XmlDocument xlm = Json2Xml(info);
            return xlm.InnerXml;

        }
        public string ConvertXmlToString(XmlDocument xmlDoc)
        {
            MemoryStream stream = new MemoryStream();
            XmlTextWriter writer = new XmlTextWriter(stream, null);
            writer.Formatting = System.Xml.Formatting.Indented;
            xmlDoc.Save(writer);
            StreamReader sr = new StreamReader(stream, System.Text.Encoding.UTF8);
            stream.Position = 0;
            string xmlString = sr.ReadToEnd();
            sr.Close();
            stream.Close();
            return xmlString;
        }

        public static XmlDocument Json2Xml(string sJson)
        {
            //XmlDictionaryReader reader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(sJson), XmlDictionaryReaderQuotas.Max);  
            //XmlDocument doc = new XmlDocument();  
            //doc.Load(reader);  

            JavaScriptSerializer oSerializer = new JavaScriptSerializer();
            Dictionary<string, object> Dic = (Dictionary<string, object>)oSerializer.DeserializeObject(sJson);
            XmlDocument doc = new XmlDocument();
            XmlDeclaration xmlDec;
          
            XmlElement nRoot = doc.CreateElement("xml");
            doc.AppendChild(nRoot);
            foreach (KeyValuePair<string, object> item in Dic)
            {
                XmlElement element = doc.CreateElement(item.Key);
                KeyValue2Xml(element, item);
                nRoot.AppendChild(element);
            }
            return doc;
        }

        private static void KeyValue2Xml(XmlElement node, KeyValuePair<string, object> Source)
        {
            object kValue = Source.Value;
            if (kValue.GetType() == typeof(Dictionary<string, object>))
            {
                foreach (KeyValuePair<string, object> item in kValue as Dictionary<string, object>)
                {
                    XmlElement element = node.OwnerDocument.CreateElement(item.Key);
                    KeyValue2Xml(element, item);
                    node.AppendChild(element);
                }
            }
            else if (kValue.GetType() == typeof(object[]))
            {
                object[] o = kValue as object[];
                for (int i = 0; i < o.Length; i++)
                {
                    XmlElement xitem = node.OwnerDocument.CreateElement("Item");
                    KeyValuePair<string, object> item = new KeyValuePair<string, object>("Item", o[i]);
                    KeyValue2Xml(xitem, item);
                    node.AppendChild(xitem);
                }

            }
            else
            {
                XmlText text = node.OwnerDocument.CreateTextNode(kValue.ToString());
                node.AppendChild(text);
            }
        }
        #endregion

        #region 执行微信服务器认证操作
        public void actionManager()
        {
            string postStr = "";
            //配置信息，只有在微信做提交配置的时候才会执行。
            Valid();
            if (contextWithBase.Request.HttpMethod.ToLower() == "post")
            {

                postStr = PostInput();
                if (false == string.IsNullOrEmpty(postStr))
                {
                    //  ResponseMsg(postStr);
                }
            }


        }
        #endregion
        #region 检验signature
        private void Valid()
        {
            //微信服务器配置提交时，echoStr才不为空。
            if (echostr != null)
            {
                if (CheckSignature())
                {
                    if (!string.IsNullOrEmpty(echostr))
                    {

                        contextWithBase.Response.Write(echostr);
                    }
                }
            }
        }
        #endregion
        #region 验证微信签名
        /// <summary>      
        /// 获取POST返回来的数据      
        /// </summary>      
        /// <returns></returns>
        private string PostInput()
        {
            try
            {
                System.IO.Stream s = contextWithBase.Request.InputStream;
                int count = 0;
                byte[] buffer = new byte[s.Length];
                StringBuilder builder = new StringBuilder();
                while ((count = s.Read(buffer, 0, buffer.Length)) > 0)
                {
                    builder.Append(contextWithBase.Request.ContentEncoding.GetString(buffer, 0, count));
                }
                s.Flush();
                s.Close();
                s.Dispose();
                return builder.ToString();
            }
            catch (Exception ex)
            { throw ex; }

        }

        private bool CheckSignature()
        {

            string[] ArrTmp = { Constance.wechatToken, timestamp, nonce };
            Array.Sort(ArrTmp);     //字典排序          
            string tmpStr = string.Join("", ArrTmp);
            tmpStr = SHA1(tmpStr);
            tmpStr = tmpStr.ToLower();
            if (tmpStr == signature)
            {
                return true;
            }
            else
            {
                return false;
            }

        }
        #endregion
        #region 哈希加密
        public static string SHA1(string content)
        {
            return SHA1(content, Encoding.UTF8);
        }

        public static string SHA1(string content, Encoding encode)
        {
            try
            {
                SHA1 sha1 = new SHA1CryptoServiceProvider();
                byte[] bytes_in = encode.GetBytes(content);
                byte[] bytes_out = sha1.ComputeHash(bytes_in);
                sha1.Dispose();
                string result = BitConverter.ToString(bytes_out);
                result = result.Replace("-", "");
                return result;
            }
            catch (Exception ex)
            {
                throw new Exception("SHA1加密出错：" + ex.Message);
            }
        }
        #endregion
        #region 参数进行排序
        public static String getParamSrc(Dictionary<string, string> paramsMap)
        {
            var vDic = (from objDic in paramsMap orderby objDic.Key ascending select objDic);
            StringBuilder str = new StringBuilder();
            foreach (KeyValuePair<string, string> kv in vDic)
            {
                string pkey = kv.Key;
                string pvalue = kv.Value;
                str.Append(pkey + "=" + pvalue + "&");
            }

            String result = str.ToString().Substring(0, str.ToString().Length - 1);
            return result;
        }
        #endregion

        #region 其他
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
        #endregion
   
    }
}